
import config
import table
import path

class Schema:
    def __init__(self, canvas, cfg=None):
        if cfg is None:
            cfg = config.Configuration()
        self.cfg = cfg
        self.canvas = canvas
        self.nameToTable = {}
        self.foreignKeys = []
        self.paths = None
        self.frozen = False
    def draw(self):
        self.canvas.setBackgroundCallback("Schema")
        self.compute_geometry()
        self.prepare()
        for t in self.nameToTable.values():
            t.draw()
        for p in self.paths:
            p.draw()
    def compute_geometry(self):
        if self.frozen:
            # already done
            return
        for table in self.nameToTable.values():
            table.compute_geometry()
        self.frozen = True
    def prepare(self):
        "assign paths"
        self.compute_geometry()
        self.paths = []
        # TEMPORARY
        minimum = 0
        maximum = 1
        srcmin = 0
        srcmax = 1
        for (tableName, fromFields, srcmin, srcmax, toTableName, minimum, maximum) in self.foreignKeys:
            theTable = self.nameToTable[tableName]
            toTable = self.nameToTable[toTableName]
            toPrimaryKey = toTable.primary_key
            originWidget = theTable.group_to_widget[fromFields]
            destinationWidget = toTable.group_to_widget[toPrimaryKey]
            origins = originWidget.destinationMap()
            destinations = destinationWidget.destinationMap()
            barriers = self.allBarriers(origins, destinations)
            (start, end, points) = path.getPath(origins, destinations, barriers, self.cfg.delta)
            thePath = path.CardinalPath(start, points, end, minimum, maximum, self.canvas, origins, destinations,
                                        srcmin=srcmin, srcmax=srcmax)
            self.paths.append(thePath)
        #self.paths = paths
    def allBarriers(self, origins, destinations):
        barriers = {}
        for t in self.nameToTable.values():
            barriers.update(t.barriers())
        for p in origins.keys()+destinations.keys():
            if barriers.has_key(p):
                del barriers[p]
        for p in self.paths:
            barriers.update(p.barriers())
        return barriers
    def addTable(self, name, x, y):
        assert not self.frozen, "cannot modify after freeze"
        theTable = table.Table(name, self.canvas, x, y, self.cfg)
        self.nameToTable[name] = theTable
    def addFieldGroup(self, tableName, fields):
        assert not self.frozen, "cannot modify after freeze"
        theTable = self.nameToTable[tableName]
        theTable.add_attribute_group(fields)
    def addPrimaryKey(self, tableName, fields):
        assert not self.frozen, "cannot modify after freeze"
        theTable = self.nameToTable[tableName]
        theTable.add_primary_key(fields)
    def addForeignKey(self, tableName, fromFields, toTableName, frommin=0, frommax=1, tomin=0, tomax="many"):
        #pr "addForeignKey", (self, tableName, fromFields, toTableName, frommin, frommax, tomin, tomax)
        assert not self.frozen, "cannot modify after freeze"
        theTable = self.nameToTable[tableName]
        toTable = self.nameToTable[toTableName]
        toPrimaryKey = toTable.primary_key
        if toPrimaryKey is None:
            raise ValueError, "no primary key defined for "+repr(tableName)
        fromFields = table.normalizeAttributes(fromFields)
        if not fromFields in theTable.attribute_groups:
            raise ValueError, "no such source attribute grouping "+repr(fromFields)
        record = (tableName, fromFields, frommin, frommax, toTableName, tomin, tomax)
        self.foreignKeys.append(record)

def test(fontdir=".", outfile="/tmp/out4.png"):
    from skimpyGimpy import canvas
    from entity import Entity
    c = canvas.Canvas()
    c.addFont("propell", fontdir+"/propell.bdf")
    S = Schema(c)
    S.addTable("EMPLOYEE", 0, 0)
    S.addFieldGroup("EMPLOYEE", ("NAME", "IQ"))
    S.addFieldGroup("EMPLOYEE", ("dnum",))
    S.addPrimaryKey("EMPLOYEE", ("EID",))
    S.addTable("DEPT", 300, 0)
    S.addPrimaryKey("DEPT", ('dnum',))
    S.addFieldGroup("DEPT", ('NAME', 'DESCR'))
    S.addForeignKey("EMPLOYEE", ("dnum",), "DEPT")
    S.addForeignKey("EMPLOYEE", ("NAME", "IQ"), "DEPT", frommin=1)
    S.addForeignKey("DEPT", ('NAME', 'DESCR'), "EMPLOYEE")
    S.addForeignKey("DEPT", ('dnum',), "EMPLOYEE")
    S.draw()
    c.dumpToPNG(outfile)
    print "test output to", outfile


if __name__=="__main__":
    test()
